import json

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.forms import model_to_dict
from django.urls import reverse

from web.forms.file import FolderModelFrom, FileModelForm
from web import models

from utils.tencent.cos import delete_file, delete_file_list, credential


@csrf_exempt
def file(request, project_id):
    """ 文件列表 & 添加"""

    # http://127.0.0.1:8000/manage/5/file/     根目录建
    # http://127.0.0.1:8000/manage/5/file/?folder=5    不是在根目录创建
    parent_object = None
    folder_id = request.GET.get('folder')

    if folder_id:
        if folder_id.isdecimal():
            parent_object = models.FileRepository.objects.filter(id=int(folder_id), file_type=2, project=request.bug_platform.project).first()

    # get是查看页面
    if request.method == 'GET':

        breadcrumb_list = []  # 循环的列表
        parent = parent_object
        while parent:
            # breadcrumb_list.insert(0, {'id': parent.id, 'name': parent.name})
            # model_to_dict(对象, [对象的属性]) 模型对象变成字典【 自动变成字典
            breadcrumb_list.insert(0, model_to_dict(parent, ['id', 'name']))
            parent = parent.parent

        # print(breadcrumb_list)

        # 文件列表 当前目录下的所有文件和文件夹【当前项目
        queryset = models.FileRepository.objects.filter(project=request.bug_platform.project)

        if parent_object:
            # 有值表示已经进人某个目录 【.order_by('-file_type')倒序排序
            file_object_list = queryset.filter(parent=parent_object).order_by('-file_type')
        else:
            # 根mul
            file_object_list = queryset.filter(parent__isnull=True).order_by('-file_type')

        form = FolderModelFrom(request, parent_object)
        context = {
            "form": form,
            'file_object_list': file_object_list,
            'breadcrumb_list': breadcrumb_list,
            'folder': parent_object
        }
        return render(request, 'file.html', context)

    # post是添加文件夹 & 文件夹修改

    fid = request.POST.get('fid')
    edit_object = None
    if fid.isdecimal():
        # 有效值就是修改
        edit_object = models.FileRepository.objects.filter(id=int(fid), file_type=2, project=request.bug_platform.project).first()

    if edit_object:
        form = FolderModelFrom(request, parent_object, data=request.POST, instance=edit_object)
    else:
        form = FolderModelFrom(request, parent_object, data=request.POST)
    if form.is_valid():
        form.instance.project = request.bug_platform.project
        form.instance.file_type = 2
        form.instance.update_user = request.bug_platform.user
        form.instance.parent = parent_object
        form.save()
        return JsonResponse({"status": True})

    return JsonResponse({"status": False, 'error': form.errors})


# http://127.0.0.1:8000/manage/5/file/delete/?fid=1
def file_delete(request, project_id):
    """ 文件  的删除 """
    fid = request.GET.get('fid')
    # project=request.bug_platform.project 当前用户的文件
    # 删除 数据库中的 文件和文件夹 【级联删除
    # models.FileRepository.objects.filter(id=fid, project=request.bug_platform.project).delete()
    delete_object = models.FileRepository.objects.filter(id=fid, project=request.bug_platform.project).first()
    # print(type(delete_object), '123456')
    # delete_object 要删除的文件对象
    if delete_object.file_type == '1':
        print('1')
        # 删除文件 【数据库中的文件删除, cos里要删除, 项目已使用的空间容量归还给用户
        # 字节 / 删除文件 / 将容量还给当前项目已使用空间
        request.bug_platform.project.use_space -= delete_object.file_size  # 用户使用空间等于使用空间-删除文件的空间
        request.bug_platform.project.save()  # 更新保存

        # cos 中删除文件
        delete_file(
            request.bug_platform.project.bucket,
            request.bug_platform.project.region,
            delete_object.key
        )

        delete_object.delete()
        return JsonResponse({'status': True})

    # 删除文件夹 【找到文件夹下的所有文件 做【数据库中的文件删除, cos里要删除, 项目已使用的空间容量归还给用户
    # 找到删除对象下的 文件和文件夹
    # models.FileRepository.objects.filter(parent=delete_object) # 遇到文件 删除/ 文件夹 继续向里找

    from django.db.models import Sum
    # total_size = models.FileRepository.objects.all().aggregate(Sum('file_size'))
    total_size = 0
    key_list = []

    folder_list = [delete_object.parent, ]  # 目录列表
    for folder in folder_list:
        child_list = models.FileRepository.objects.filter(project=request.bug_platform.project, parent=folder).order_by('-file_type')  # 倒序 文件夹在上面
        for child in child_list:
            if child.file_type == '2':
                folder_list.append(child)
            else:
                # 文件大小汇总
                total_size += child.file_size
                # 删除【 一个文件一个文件的删除
                # delete_file(request.bug_platform.project.bucket, request.bug_platform.project.region, child.key)
                key_list.append({'Key': child.key})

    print('total_size', total_size)
    # 批量删除cos文件
    if key_list:
        delete_file_list(request.bug_platform.project.bucket, request.bug_platform.project.region, key_list)
    # 归还容量
    if total_size:
        request.bug_platform.project.use_space -= total_size  # 用户使用空间等于使用空间-删除文件的空间
        # request.bug_platform.project.use_space = total_size.get('file_size__sum')
        request.bug_platform.project.save()  # 更新保存

    # 删除数据库中的
    delete_object.delete()
    return JsonResponse({'status': True})


@csrf_exempt
def cos_credential(request, project_id):
    """ 获取cos临时凭证 """
    per_file_limit = request.bug_platform.price_policy.per_file_size * 1024 * 1024  # 把兆变成字节

    total_size = 0  # 上传全部文件的总大小
    file_list = json.loads(request.body.decode('utf-8'))  # 获取要上传的每个文件 & 大小
    # 容量限制：单文件
    for item in file_list:
        # item['size'] 文件的字节大小 = B
        # print(item['name'], item['size'])
        # 单文件限制大小【m 兆   request.bug_platform.price_policy.per_file_size
        if item['size'] > per_file_limit:
            # 超出限制
            msg = f'单文件超级限制(最大{request.bug_platform.price_policy.per_file_size}M), 文件: {item["name"]}, 请升级套餐'
            return JsonResponse({'status': False, 'error': msg})
        total_size += item['size']

    # 容量限制：总容量
    project_space = request.bug_platform.price_policy.project_space  # 项目允许的总空间
    use_space = request.bug_platform.project.use_space  # 项目已使用的空间
    if use_space + total_size > project_space * 1024 * 1024:
        return JsonResponse({'status': False, 'error': '容量超过限制，请升级套餐'})

    data_dict = credential(request.bug_platform.project.bucket, request.bug_platform.project.region)
    # print(data_dict)
    return JsonResponse({'status': True, 'data': data_dict})


@csrf_exempt
def file_post(request, project_id):
    """ 上传成功后返回到后台 将数据保存到数据库 """
    '''
        'name': fileNmae,  文件名
        'file_size': fileSize,  文件大小
        'key': key,         文件别名
        'parent': CURRENT_FOLDER_ID,    文件父级目录
        'file_path': data.Location,     文件路径
        'etag': data.ETag,              文件的cos名
    '''
    # 可以根据key去cos获取文件的etag 和 浏览器返回的etag校验
    # print(request.POST)
    # 通过ModelForm.save存储到数据库的数据返回的instance对象,无法通过get_xx_display获取到choice的中文
    form = FileModelForm(request, data=request.POST)
    if form.is_valid():
        # 校验通过 将数据写入数据库
        # form.instance.file_type = 1
        # form.instance.update_user = request.bug_platform.user
        # form.save()

        data_dict = form.cleaned_data
        data_dict.pop('etag')
        data_dict.update({
            'project': request.bug_platform.project,
            'file_type': 1,
            'update_user': request.bug_platform.user
        })
        instance = models.FileRepository.objects.create(**data_dict)

        # 项目的已使用的空间: 更新
        # request.bug_platform.project.use_space += data_dict['file_size']

        from django.db.models import Sum
        total_size = models.FileRepository.objects.all().aggregate(Sum('file_size'))
        request.bug_platform.project.use_space = total_size.get('file_size__sum')
        request.bug_platform.project.save()  # 保存

        result = {
            'id': instance.id,
            'name': instance.name,
            'file_size': instance.file_size,
            'update_user__username': instance.update_user.username,
            'datetime': instance.update_datetime.strftime("%Y年%m月%d日 %H:%M"),
            'download_url': reverse('file_download', kwargs={'project_id': project_id, 'file_id': instance.id})
            # 'file_type': instance.get_file_type_display(),
        }
        return JsonResponse({'status': True, 'data': result})

    return JsonResponse({'status': False, 'error': form.errors})


def file_download(request, project_id, file_id):
    """ 文件下载 """
    # 文件内容
    # 响应头

    # 打开文件， 获取文件的内容 ; 去cos获取内容
    import requests
    # models.FileRepository.objects.filter(id=file_id, project=request.bug_platform.project).first()
    file_object = models.FileRepository.objects.filter(id=file_id, project_id=project_id).first()
    url = file_object.file_path
    data = requests.get(url)
    response = HttpResponse(data)
    # 设置响应头
    response['Content-Disposition'] = f"attachment; filename={file_object.name}"
    return response
